package com.collect.senegal.zhiUtils;

import android.content.Context;
import android.content.SharedPreferences;

import androidx.annotation.NonNull;
import androidx.collection.SimpleArrayMap;

import com.collect.senegal.MyApplication;
import com.collect.senegal.zhiGlobal.zhiAppSettings.ZHIProjectConstants;

import java.util.Collections;
import java.util.Map;
import java.util.Set;


public class SPUtils {

	private static SimpleArrayMap<String, SPUtils> SP_UTILS_MAP = new SimpleArrayMap<>();
	private SharedPreferences sp;

	/**
	 * 获取SP实例
	 *
	 * @return {@link SPUtils}
	 */
	public static SPUtils getInstance() {
		return getInstance(null);
	}

	/**
	 * 获取SP实例
	 *
	 * @param spName sp名
	 * @return {@link SPUtils}
	 */
	public static SPUtils getInstance(String spName) {
		if (isSpace(spName)) spName = ZHIProjectConstants.SHARED_NAME;
		SPUtils spUtils = SP_UTILS_MAP.get(spName);
		if (spUtils == null) {
			spUtils = new SPUtils(spName);
			SP_UTILS_MAP.put(spName, spUtils);
		}
		return spUtils;
	}

	private SPUtils(final String spName) {
		sp = MyApplication.getApp().getSharedPreferences(spName, Context.MODE_PRIVATE);
	}

	/**
	 * SP中写入String
	 *
	 * @param key   键
	 * @param value 值
	 */
	public void put(@NonNull final String key, @NonNull final String value) {
		put(key, value, false);
	}

	/**
	 * SP中写入String
	 *
	 * @param key      键
	 * @param value    值
	 * @param isCommit {@code true}: {@link SharedPreferences.Editor#commit()}<br>
	 *                 {@code false}: {@link SharedPreferences.Editor#apply()}
	 */
	public void put(@NonNull final String key, @NonNull final String value, final boolean isCommit) {
		if (isCommit) {
			sp.edit().putString(key, value).commit();
		} else {
			sp.edit().putString(key, value).apply();
		}
	}

	public <T> T getObject(@NonNull final String key, Class<T> clazz){
		String json = getString(key);
		return GsonUtil.convertObj(json, clazz);
	}
	public void putObject(@NonNull final String key, @NonNull final Object value, final boolean isCommit) {
		put(key, GsonUtil.toJson(value), isCommit);
	}
	/**
	 * SP中读取String
	 *
	 * @param key 键
	 * @return 存在返回对应值，不存在返回默认值{@code ""}
	 */
	public String getString(@NonNull final String key) {
		return getString(key, "");
	}

	/**
	 * SP中读取String
	 *
	 * @param key          键
	 * @param defaultValue 默认值
	 * @return 存在返回对应值，不存在返回默认值{@code defaultValue}
	 */
	public String getString(@NonNull final String key, @NonNull final String defaultValue) {
		return sp.getString(key, defaultValue);
	}

	/**
	 * SP中写入int
	 *
	 * @param key   键
	 * @param value 值
	 */
	public void put(@NonNull final String key, final int value) {
		put(key, value, false);
	}

	/**
	 * SP中写入int
	 *
	 * @param key      键
	 * @param value    值
	 * @param isCommit {@code true}: {@link SharedPreferences.Editor#commit()}<br>
	 *                 {@code false}: {@link SharedPreferences.Editor#apply()}
	 */
	public void put(@NonNull final String key, final int value, final boolean isCommit) {
		if (isCommit) {
			sp.edit().putInt(key, value).commit();
		} else {
			sp.edit().putInt(key, value).apply();
		}
	}

	/**
	 * SP中读取int
	 *
	 * @param key 键
	 * @return 存在返回对应值，不存在返回默认值-1
	 */
	public int getInt(@NonNull final String key) {
		return getInt(key, -1);
	}

	/**
	 * SP中读取int
	 *
	 * @param key          键
	 * @param defaultValue 默认值
	 * @return 存在返回对应值，不存在返回默认值{@code defaultValue}
	 */
	public int getInt(@NonNull final String key, final int defaultValue) {
		return sp.getInt(key, defaultValue);
	}

	/**
	 * SP中写入long
	 *
	 * @param key   键
	 * @param value 值
	 */
	public void put(@NonNull final String key, final long value) {
		put(key, value, false);
	}

	/**
	 * SP中写入long
	 *
	 * @param key      键
	 * @param value    值
	 * @param isCommit {@code true}: {@link SharedPreferences.Editor#commit()}<br>
	 *                 {@code false}: {@link SharedPreferences.Editor#apply()}
	 */
	public void put(@NonNull final String key, final long value, final boolean isCommit) {
		if (isCommit) {
			sp.edit().putLong(key, value).commit();
		} else {
			sp.edit().putLong(key, value).apply();
		}
	}

	/**
	 * SP中读取long
	 *
	 * @param key 键
	 * @return 存在返回对应值，不存在返回默认值-1
	 */
	public long getLong(@NonNull final String key) {
		return getLong(key, -1L);
	}

	/**
	 * SP中读取long
	 *
	 * @param key          键
	 * @param defaultValue 默认值
	 * @return 存在返回对应值，不存在返回默认值{@code defaultValue}
	 */
	public long getLong(@NonNull final String key, final long defaultValue) {
		return sp.getLong(key, defaultValue);
	}

	/**
	 * SP中写入float
	 *
	 * @param key   键
	 * @param value 值
	 */
	public void put(@NonNull final String key, final float value) {
		put(key, value, false);
	}

	/**
	 * SP中写入float
	 *
	 * @param key      键
	 * @param value    值
	 * @param isCommit {@code true}: {@link SharedPreferences.Editor#commit()}<br>
	 *                 {@code false}: {@link SharedPreferences.Editor#apply()}
	 */
	public void put(@NonNull final String key, final float value, final boolean isCommit) {
		if (isCommit) {
			sp.edit().putFloat(key, value).commit();
		} else {
			sp.edit().putFloat(key, value).apply();
		}
	}

	/**
	 * SP中读取float
	 *
	 * @param key 键
	 * @return 存在返回对应值，不存在返回默认值-1
	 */
	public float getFloat(@NonNull final String key) {
		return getFloat(key, -1f);
	}

	/**
	 * SP中读取float
	 *
	 * @param key          键
	 * @param defaultValue 默认值
	 * @return 存在返回对应值，不存在返回默认值{@code defaultValue}
	 */
	public float getFloat(@NonNull final String key, final float defaultValue) {
		return sp.getFloat(key, defaultValue);
	}

	/**
	 * SP中写入boolean
	 *
	 * @param key   键
	 * @param value 值
	 */
	public void put(@NonNull final String key, final boolean value) {
		put(key, value, false);
	}

	/**
	 * SP中写入boolean
	 *
	 * @param key      键
	 * @param value    值
	 * @param isCommit {@code true}: {@link SharedPreferences.Editor#commit()}<br>
	 *                 {@code false}: {@link SharedPreferences.Editor#apply()}
	 */
	public void put(@NonNull final String key, final boolean value, final boolean isCommit) {
		if (isCommit) {
			sp.edit().putBoolean(key, value).commit();
		} else {
			sp.edit().putBoolean(key, value).apply();
		}
	}

	/**
	 * SP中读取boolean
	 *
	 * @param key 键
	 * @return 存在返回对应值，不存在返回默认值{@code false}
	 */
	public boolean getBoolean(@NonNull final String key) {
		return getBoolean(key, false);
	}

	/**
	 * SP中读取boolean
	 *
	 * @param key          键
	 * @param defaultValue 默认值
	 * @return 存在返回对应值，不存在返回默认值{@code defaultValue}
	 */
	public boolean getBoolean(@NonNull final String key, final boolean defaultValue) {
		return sp.getBoolean(key, defaultValue);
	}

	/**
	 * SP中写入String集合
	 *
	 * @param key    键
	 * @param values 值
	 */
	public void put(@NonNull final String key, @NonNull final Set<String> values) {
		put(key, values, false);
	}

	/**
	 * SP中写入String集合
	 *
	 * @param key      键
	 * @param values   值
	 * @param isCommit {@code true}: {@link SharedPreferences.Editor#commit()}<br>
	 *                 {@code false}: {@link SharedPreferences.Editor#apply()}
	 */
	public void put(@NonNull final String key, @NonNull final Set<String> values, final boolean isCommit) {
		if (isCommit) {
			sp.edit().putStringSet(key, values).commit();
		} else {
			sp.edit().putStringSet(key, values).apply();
		}
	}

	/**
	 * SP中读取StringSet
	 *
	 * @param key 键
	 * @return 存在返回对应值，不存在返回默认值{@code Collections.<String>emptySet()}
	 */
	public Set<String> getStringSet(@NonNull final String key) {
		return getStringSet(key, Collections.<String>emptySet());
	}

	/**
	 * SP中读取StringSet
	 *
	 * @param key          键
	 * @param defaultValue 默认值
	 * @return 存在返回对应值，不存在返回默认值{@code defaultValue}
	 */
	public Set<String> getStringSet(@NonNull final String key, @NonNull final Set<String> defaultValue) {
		return sp.getStringSet(key, defaultValue);
	}

	/**
	 * SP中获取所有键值对
	 *
	 * @return Map对象
	 */
	public Map<String, ?> getAll() {
		return sp.getAll();
	}

	/**
	 * SP中是否存在该key
	 *
	 * @param key 键
	 * @return {@code true}: 存在<br>{@code false}: 不存在
	 */
	public boolean contains(@NonNull final String key) {
		return sp.contains(key);
	}

	/**
	 * SP中移除该key
	 *
	 * @param key 键
	 */
	public void remove(@NonNull final String key) {
		remove(key, false);
	}

	/**
	 * SP中移除该key
	 *
	 * @param key      键
	 * @param isCommit {@code true}: {@link SharedPreferences.Editor#commit()}<br>
	 *                 {@code false}: {@link SharedPreferences.Editor#apply()}
	 */
	public void remove(@NonNull final String key, final boolean isCommit) {
		if (isCommit) {
			sp.edit().remove(key).commit();
		} else {
			sp.edit().remove(key).apply();
		}
	}

	/**
	 * SP中清除所有数据
	 */
	public void clear() {
		clear(false);
	}

	/**
	 * SP中清除所有数据
	 *
	 * @param isCommit {@code true}: {@link SharedPreferences.Editor#commit()}<br>
	 *                 {@code false}: {@link SharedPreferences.Editor#apply()}
	 */
	public void clear(final boolean isCommit) {
		if (isCommit) {
			sp.edit().clear().commit();
		} else {
			sp.edit().clear().apply();
		}
	}

	private static boolean isSpace(final String s) {
		if (s == null) return true;
		for (int i = 0, len = s.length(); i < len; ++i) {
			if (!Character.isWhitespace(s.charAt(i))) {
				return false;
			}
		}
		return true;
	}
	
}
